#include "matriz.h"
#include <math.h>
#include <cassert>
#include <cmath>

/*
 * Mapea coordenadas de una matriz con subindices que comienzan
 * desde 1 a coordenadas para un vector que comienza en 0.
 */
Indice deCoordsAIndice(Indice i, Indice j, Tam m) {
	return (i - 1) * m + j - 1;
}

/*
 * Matriz
 */
Matriz::Matriz(Tam cantidadDeFilas, Tam cantidadDeColumnas) :
	_cantidadDeFilas	(cantidadDeFilas),
	_cantidadDeColumnas	(cantidadDeColumnas),
	_vector				(_cantidadDeFilas * _cantidadDeColumnas)
{
	for (Indice i = 0; i < _vector.size(); i++) {
		_vector[i] = 0;
	}
}

double Matriz::get(Indice i, Indice j) const {
	assert(1 <= i && i <= _cantidadDeFilas && 1 <= j && j <= _cantidadDeColumnas);

	return _vector[deCoordsAIndice(i, j, _cantidadDeColumnas)];
}

void Matriz::set(Indice i, Indice j, double valor) {
	assert(1 <= i && i <= _cantidadDeFilas && 1 <= j && j <= _cantidadDeColumnas);

	_vector[deCoordsAIndice(i, j, _cantidadDeColumnas)] = valor;
}

Tam Matriz::cantidadDeFilas() const {
	return _cantidadDeFilas;
}

Tam Matriz::cantidadDeColumnas() const {
	return _cantidadDeColumnas;
}

void Matriz::getPosicionMaxElementoSubmatriz(Indice submatriz, Indice& fila, Indice& columna){
	Tam j,i;
	fila= submatriz;
	columna= submatriz;
	double max, act;
	max= fabs(this->get(fila, columna));

	for(j=submatriz;j<=this->cantidadDeFilas();j++){
		for(i=submatriz;i<=this->cantidadDeColumnas();i++){		
			act= fabs(this->get(j,i));
			if (max<act){
				fila= j;
				columna= i;
				max= act;
			}
		}
	}	
}

void Matriz::swapColumna(Indice columna1, Indice columna2){
	double aux;
	for(Tam i=1;i<=this->cantidadDeFilas();i++){
		aux= this->get(i,columna1);
		this->set(i,columna1,this->get(i,columna2));
		this->set(i,columna2,aux);
	}
}

void Matriz::swapFila(Indice fila1, Indice fila2){
	double aux;
	for(Tam i=1;i<=this->cantidadDeColumnas();i++){
		aux= this->get(fila1,i);
		this->set(fila1,i,this->get(fila2, i));
		this->set(fila2,i,aux);
	}
}

/*
 * setTam
 */
void Matriz::setTam(Tam cantidadDeFilas, Tam cantidadDeColumnas) {
	_cantidadDeFilas	= cantidadDeFilas;
	_cantidadDeColumnas	= cantidadDeColumnas;
	_vector.resize(_cantidadDeFilas * _cantidadDeColumnas);
}

void Matriz::copiarMatriz(const Matriz* m)
{
	if(_cantidadDeFilas != m->cantidadDeFilas() && _cantidadDeColumnas != m->cantidadDeColumnas())
			this->setTam(m->cantidadDeFilas(),m->cantidadDeColumnas());
	for(Indice j=1;j<=_cantidadDeColumnas;j++)
		for(Indice i=1;i<=_cantidadDeFilas;i++)
			this->set(i,j,m->get(i,j));
}

void Matriz::trasponer()
{
	Matriz m(this->cantidadDeFilas(),this->cantidadDeColumnas());
	m.copiarMatriz(this);
	this->setTam(m.cantidadDeColumnas(),m.cantidadDeFilas());
	for(Indice i=1;i<=this->cantidadDeFilas();i++)
		for(Indice j=1;j<=this->cantidadDeColumnas();j++)
			this->set(i,j,m.get(j,i));
	
	
}
